package robot

import (
	"gamesdk/wanyu/server/api/gameapi/games/ddz/logic"
	"gamesdk/wanyu/server/protogo/gameddz"
	"reflect"
	"gamesdk/wanyu/server/engine/utils"
	errors "gamesdk/wanyu/server/engine/wperror"
	wplog "gamesdk/wanyu/server/engine/wplog"
)

func (rb *robot) processPlayerInfos(playerinfos []*gameddz.PlayerInfo) {
	for _, playerinfo := range playerinfos {
		rb.handCardsCount[playerinfo.Seat] = playerinfo.Cardcount
		if playerinfo.Seat == rb.mySeat {
			rb.handCards = nil
			for _, card := range playerinfo.Handcards {
				rb.handCards = append(rb.handCards, logic.Card{
					Number: int(card.Number),
					Flower: logic.FlowerType(card.Flower),
				})
			}
			rb.handCards = logic.SortCards(rb.handCards)

		}
	}
}

func (rb *robot) processTableInfo(tableinfo *gameddz.TableInfo) bool {
	var bnewstep = rb.gameStep != tableinfo.Gamestep
	rb.gameStep = tableinfo.Gamestep
	rb.bankerSeat = tableinfo.Bankerseat
	rb.currentSeat = tableinfo.Currentseat
	rb.threeCards = nil
	for _, card := range tableinfo.Threecards {
		rb.threeCards = append(rb.threeCards, logic.Card{
			Number: int(card.Number),
			Flower: logic.FlowerType(card.Flower),
		})
	}
	// if -1 == tableinfo.Outcards.Seat {
	// 	rb.maxOutSeat = -1
	// 	rb.maxOutCards = nil
	// } else {
	// 	rb.maxOutSeat = tableinfo.Outcards.Seat
	// 	rb.maxOutCards = nil
	// 	for _, card := range tableinfo.Outcards.Cards {
	// 		rb.maxOutCards = append(rb.maxOutCards, logic.Card{
	// 			Number: int(card.Number),
	// 			Flower: logic.FlowerType(card.Flower),
	// 		})
	// 	}
	// }
	return bnewstep
}

//机器人开始游戏
func (rb *robot) processGameStart(gamestart *gameddz.GameStart) {

	rb.processTableInfo(gamestart.TableInfos)
	rb.processPlayerInfos(gamestart.PlayerInfos)
	rb.currentSeat = gamestart.Seat
	rb.leftCards = logic.CreateCards54Ex()
	//剩余牌减少，减掉自己的手牌
	_, rb.leftCards = logic.RemoveCards(rb.leftCards, rb.handCards)
	//只有第一个叫地主的玩家才有动画时间的延迟
	// rb.gameCfg.SendCardAni = 0
	// if rb.mySeat == gamestart.Seat {
	// 	rb.gameCfg.SendCardAni = 2000
	// }
	rb.checkRunTree()
}

func (rb *robot) processGameRound(gameround *gameddz.GameRounder) {
	rb.currentSeat = gameround.Seat
	//每个游戏阶段，不同处理
	switch rb.gameStep {
	case gameddz.GameStep_ST_CALL_BANKER:
		rb.checkRunTree()
	case gameddz.GameStep_ST_PLAYER_DOUBLE:
		//加倍动作在桌子信息里面处理
	case gameddz.GameStep_ST_OUT_CARD:
		rb.checkRunTree()
	case gameddz.GameStep_ST_ROB_BANKER:
		rb.checkRunTree()
	}
}

func (rb *robot) processCallBanker(callbanker *gameddz.CallBanker) {

}
func (rb *robot) processRobBanker(callbanker *gameddz.RobBanker) {

}

func (rb *robot) processEnsureBanker(ensurebanker *gameddz.EnsureBanker) {
	rb.bankerSeat = ensurebanker.Bankerseat
	rb.threeCards = nil
	for _, card := range ensurebanker.Threecards {
		rb.threeCards = append(rb.threeCards, logic.Card{
			Number: int(card.Number),
			Flower: logic.FlowerType(card.Flower),
		})
	}
	if rb.bankerSeat == rb.mySeat {
		rb.handCards = logic.AddCards(rb.handCards, rb.threeCards)
		//剩余牌减少，减掉地主三张牌
		_, rb.leftCards = logic.RemoveCards(rb.leftCards, rb.threeCards)
	}
	//手牌增加
	rb.handCardsCount[rb.bankerSeat] += 3
}

func (rb *robot) processPlayerDouble(playerdouble *gameddz.PlayerDouble) {
	//玩家加倍信息
}

func (rb *robot) processStartOutCard(isStart bool, gameround *gameddz.GameRounder) {
	if isStart {
		rb.round = 0
	} else {
		rb.round++
	}
	rb.currentSeat = gameround.Seat
	rb.firstOutSeat = rb.currentSeat
	//当前回合最大出牌玩家
	rb.maxOutSeat = -1
	//当前回合最大出牌牌组
	rb.maxOutCards = nil
	//玩家pass信息重置
	for k := range rb.isPassCard {
		rb.isPassCard[k] = false
	}
	rb.checkRunTree()
}

func (rb *robot) processOutCard(outcard *gameddz.OutCard) {
	rb.isPassCard[outcard.Seat] = outcard.Option == gameddz.OptionType_OP_PASS_CARD
	//牌局出牌记录
	var out outData
	out.round = rb.round
	out.option = outcard.Option
	for _, card := range outcard.Outcards {
		out.cards = append(out.cards, logic.Card{
			Number: int(card.Number),
			Flower: logic.FlowerType(card.Flower),
		})
	}
	var earlyMaxCards []logic.Card
	for _, card := range outcard.EarlyMaxCards {
		earlyMaxCards = append(earlyMaxCards, logic.Card{
			Number: int(card.Number),
			Flower: logic.FlowerType(card.Flower),
		})
	}
	rb.outCards[outcard.Seat] = append(rb.outCards[outcard.Seat], &out)
	if rb.isPassCard[outcard.Seat] == true {
		rb.lastPassCardType[outcard.Seat] = logic.GetCardsType(earlyMaxCards)
	} else {
		rb.lastOutCardType[outcard.Seat] = logic.GetCardsType(out.cards)
	}

	if outcard.Option != gameddz.OptionType_OP_OUT_CARD {
		return
	}
	var cards []logic.Card
	for _, card := range outcard.Outcards {
		cards = append(cards, logic.Card{
			Number: int(card.Number),
			Flower: logic.FlowerType(card.Flower),
		})
	}
	if outcard.Seat == rb.mySeat {
		var success bool
		success, rb.handCards = logic.RemoveCards(rb.handCards, cards)
		errors.Check(success, errors.ErrorLogic, "robot removecards error !!!")
	} else {
		//剩余牌减少
		_, rb.leftCards = logic.RemoveCards(rb.leftCards, cards)
	}
	//手牌减少
	rb.handCardsCount[outcard.Seat] -= int32(len(outcard.Outcards))
	//当前回合最大出牌玩家
	rb.maxOutSeat = outcard.Seat
	//当前回合最大出牌牌组
	rb.maxOutCards = cards
}

func (rb *robot) processGameEnd(gameend *gameddz.GameEnd) {
	for _, result := range gameend.Results {
		if result.Seat == rb.mySeat {
			if result.WinMoney > 0 {
				wplog.Debugf(rb.robotPlayer.GetDLogPrefix()+" rb [%d] is win !!!", result.Seat)
			} else {
				wplog.Debugf(rb.robotPlayer.GetDLogPrefix()+" rb [%d] is lose !!!", result.Seat)
			}
			break
		}
	}
	rb.resetRobotInfo()
	rb.setRobotTimer(rb.gameCfg.GameEndAni+utils.RandIntRange(300, 1000), func() {
		//event := common.MakeGameEvent(rb.robotID, int32(gameddz.Event_PLAYER_CONTINUE_REQ), nil)
		//rb.mgr.PostEvent(*event, false)
	})
}
func (rb *robot) doOut3x(t int) {

}
func (rb *robot) doCallBanker(call bool) {
	rb.setRobotTimer(utils.RandIntRange(500, 5000), func() {

		var msg gameddz.CallBanker
		msg.Seat = rb.mySeat
		msg.Yes = call
		//event := common.MakeGameEvent(rb.robotID, int32(gameddz.Event_CALL_BANKER_REQ), &msg)
		//rb.mgr.PostEvent(*event, false)
		wplog.Debug(rb.robotPlayer.GetDLogPrefix()+" ---------- robot doCallBanker: ", msg.Seat, msg.Yes)
	})
}

func (rb *robot) doRobBanker(rob bool) {
	rb.setRobotTimer(utils.RandIntRange(500, 5000), func() {

		var msg gameddz.RobBanker
		msg.Seat = rb.mySeat
		msg.Yes = rob
		//event := common.MakeGameEvent(rb.robotID, int32(gameddz.Event_ROB_BANKER_REQ), &msg)
		//rb.mgr.PostEvent(*event, false)
		wplog.Debug(rb.robotPlayer.GetDLogPrefix()+" ---------- robot doRobBanker: ", msg.Seat, msg.Yes)
	})
}
func (rb *robot) doDouble(t int) {
	rb.setRobotTimer(utils.RandIntRange(500, 5000), func() {
		var msg gameddz.PlayerDouble
		msg.Seat = rb.mySeat
		if t == 0 {
			msg.Isdouble = false
			msg.IsSuperDouble = false
		} else if t == 1 {
			msg.Isdouble = true
			msg.IsSuperDouble = false
		} else {
			msg.Isdouble = false
			msg.IsSuperDouble = true
		}

		//event := common.MakeGameEvent(rb.robotID, int32(gameddz.Event_PLAYER_DOUBLE_REQ), &msg)
		//rb.mgr.PostEvent(*event, false)
		wplog.Debug(rb.robotPlayer.GetDLogPrefix()+" ---------- robot doDouble: ", msg.Seat, msg.Isdouble)
	})
}

func (rb *robot) sendOutCardmsg(option gameddz.OptionType, cards []logic.Card) {
	rb.sendOutCardmsgEx(utils.RandIntRange(1200, 2800), option, cards)
}

func (rb *robot) sendOutCardmsgEx(ms int, option gameddz.OptionType, cards []logic.Card) {
	wplog.Debugf(rb.robotPlayer.GetDLogPrefix()+" ---------- robot outcard start: %d, %v, %v", ms, option, cards)
	rb.setRobotTimer(ms, func() {
		var msg gameddz.OutCard
		msg.Seat = rb.mySeat
		msg.Option = option
		wplog.Debugf(rb.robotPlayer.GetDLogPrefix()+" ---------- robot outcard end : %v", cards)
		for _, card := range cards {
			msg.Outcards = append(msg.Outcards, &gameddz.Card{Number: int32(card.Number), Flower: gameddz.Card_Flower(card.Flower)})
		}
		for _, card := range rb.maxOutCards {
			msg.EarlyMaxCards = append(msg.EarlyMaxCards, &gameddz.Card{Number: int32(card.Number), Flower: gameddz.Card_Flower(card.Flower)})
		}
		//event := common.MakeGameEvent(rb.robotID, int32(gameddz.Event_OUT_CARD_REQ), &msg)
		//rb.mgr.PostEvent(*event, false)
	})
}

func (rb *robot) doPassCard() {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "PassCard is illegal !!!")
	rb.sendOutCardmsg(gameddz.OptionType_OP_PASS_CARD, nil)
}

func (rb *robot) doPassCardQuick(ms int) {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "PassCard quick is illegal !!!")
	rb.sendOutCardmsgEx(ms, gameddz.OptionType_OP_PASS_CARD, nil)
}

func (rb *robot) isAllSingleOut() bool {
	// 如果手上全是单张
	if logic.IsGroupsAllSingle(rb.cardGroups) {
		length := len(rb.handCards)
		errors.Check(length > 0, errors.ErrorLogic, "hand cards len is 0, maybe error occur !!!")
		isOutOrder := (rb.exportData.IsBanker || rb.exportData.IsBankerPrev) && rb.isPlayerAlarm(false, 1)
		if isOutOrder {
			if length <= 2 {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, []logic.Card{rb.handCards[length-1]})
				return true
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, []logic.Card{rb.handCards[length-2]})
			return true
		}
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, []logic.Card{rb.handCards[0]})
		return true
	}
	return false
}

func (rb *robot) doOutCard() {
	errors.Check(nil == rb.maxOutCards, errors.ErrorLogic, "OutCard is illegal !!!")
	//是否全单张出牌
	if rb.isAllSingleOut() {
		return
	}
	//按价值排序
	rb.cardGroups = logic.SortCardGroupsByValue(rb.cardGroups)
	//优先级牌组，排在前面的优先被打出
	priorityGroups := rb.getOutCardPriorityGroups()
	for _, group := range priorityGroups {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
		return
	}
	errors.Check(false, errors.ErrorLogic, " why can't find groups cards, maybe error occur !!!")
}

func (rb *robot) getOutCardPriorityGroups() []*logic.CardGroup {
	var priorityGroups []*logic.CardGroup
	for _, group := range rb.cardGroups {
		if group.Type == logic.AIRPLANEANDSINGLE || group.Type == logic.AIRPLANEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLESTRAIGHT || group.Type == logic.DOUBLESTRAIGHT || group.Type == logic.THREESTRAIGHT {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE) && group.Value < 12 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.SINGLE || group.Type == logic.DOUBLE || group.Type == logic.THREE) && group.Value < 12 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLE || group.Type == logic.DOUBLE || group.Type == logic.THREE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.FOURANDSINGLETWO || group.Type == logic.FOURANDDOUBLETWO {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.BOMB {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.ROCKET {
			priorityGroups = append(priorityGroups, group)
		}
	}
	return priorityGroups
}
func (rb *robot) getOutCardPriorityGroups1() []*logic.CardGroup {
	var priorityGroups []*logic.CardGroup
	rb.cardGroups = logic.SortCardGroupsByValue(rb.cardGroups)
	for _, group := range rb.cardGroups {
		if group.Type == logic.AIRPLANEANDSINGLE || group.Type == logic.AIRPLANEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLESTRAIGHT || group.Type == logic.DOUBLESTRAIGHT || group.Type == logic.THREESTRAIGHT {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE) && group.Value < 13 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.DOUBLE || group.Type == logic.THREE) && group.Value < 13 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.DOUBLE || group.Type == logic.THREE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.FOURANDSINGLETWO || group.Type == logic.FOURANDDOUBLETWO {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.BOMB {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.ROCKET {
			priorityGroups = append(priorityGroups, group)
		}
	}
	return priorityGroups
}
func (rb *robot) doOutAllCard() {
	cardsType := logic.GetCardsType(rb.handCards)
	errors.Check(cardsType > logic.NONE, errors.ErrorLogic, "OutAllCard is illegal, handcard is not one group !!!")
	if nil != rb.maxOutCards {
		errors.Check(logic.CompareCards(rb.maxOutCards, rb.handCards), errors.ErrorLogic, "OutAllCard is illegal, handcard can not more than !!!")
	}
	//有可能 4个k + 大小王，或者飞机+ 大小王，也可以判断为一手牌
	//判断手上是否有王炸，有的话先出王炸
	for _, group := range rb.cardGroups {
		if group.Type == logic.ROCKET {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
			return
		}
	}
	//避免33334444这种被当成四带两对, 避免3334445555被当成飞机带两对, 333344445555这种被当成飞机带单张的情况
	bombCnt, exCnt := logic.GetGroupsBombCnt(rb.cardGroups)
	//全炸弹
	if exCnt == 0 {
		for _, group := range rb.cardGroups {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
			return
		}
	} else if exCnt == 1 && bombCnt > 0 {
		for _, group := range rb.cardGroups {
			if group.Type < logic.BOMB {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
				return
			}
		}
	}
	//是否满足4带2且外面没有能打过的炸弹，且玩家手牌不是一对或者一单， 或者单张，对子都是绝对大牌
	if cardsType == logic.FOURANDSINGLETWO || cardsType == logic.FOURANDDOUBLETWO {
		var bombGroup *logic.CardGroup
		for _, group := range rb.cardGroups {
			if group.Type == logic.BOMB {
				bombGroup = group
				break
			}
		}
		errors.Check(nil != bombGroup, errors.ErrorLogic, " why has no bomb, maybe error occur !!!")
		var mincards []logic.Card
		var maxcards []logic.Card
		for _, group := range rb.cardGroups {
			if group.Type < logic.BOMB {
				mincards = logic.CloneCards(group.Cards)
				break
			}
		}
		for i := len(rb.cardGroups) - 1; i >= 0; i-- {
			if rb.cardGroups[i].Type < logic.BOMB {
				maxcards = logic.CloneCards(rb.cardGroups[i].Cards)
				break
			}
		}
		errors.Check(0 != len(mincards), errors.ErrorLogic, " mincards len is 0, maybe error occur !!!")
		errors.Check(0 != len(maxcards), errors.ErrorLogic, " maxcards len is 0, maybe error occur !!!")
		//外面没有能大过的牌
		if exist, _ := logic.SearchLargerCardType(bombGroup.Cards, rb.leftCards, true); !exist {
			if rb.isCanSafeOutCards(maxcards, false) {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, maxcards)
				return
			}
		} else {
			if rb.isCanSafeOutCards(mincards, false) {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, mincards)
				return
			}
		}
	}
	//出完所有手牌
	rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, rb.handCards)
}

func (rb *robot) doOutAbsBig() {
	errors.Check(nil == rb.maxOutCards, errors.ErrorLogic, "OutAbsBig is illegal !!!")
	//按价值排序
	rb.cardGroups = logic.SortCardGroupsByValue(rb.cardGroups)
	//只剩2组牌
	if len(rb.cardGroups) == 2 {
		//如果外面没任何牌能打过， 例如 4，大王 或者 55，22，或者 10 + 王炸，先出绝对大牌
		for _, group := range rb.cardGroups {
			if exist, _ := logic.SearchLargerCardType(group.Cards, rb.leftCards, true); !exist {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
				return
			}
		}
		//如果没有绝对大牌，只有相对最大的，并且大牌可以压住小牌，可以先出小再出大, 例如 55，22，或者 10 + 大王，先出小牌
		if logic.CompareCards(rb.cardGroups[0].Cards, rb.cardGroups[1].Cards) && rb.isCanSafeOutCards(rb.cardGroups[0].Cards, false) {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, rb.cardGroups[0].Cards)
			return
		}
	}
	//优先级牌组，排在前面的优先被打出
	var priorityGroups []*logic.CardGroup
	for _, group := range rb.cardGroups {
		if group.Type == logic.AIRPLANEANDSINGLE || group.Type == logic.AIRPLANEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLESTRAIGHT || group.Type == logic.DOUBLESTRAIGHT || group.Type == logic.THREESTRAIGHT {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE) && group.Value < 15 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.SINGLE || group.Type == logic.DOUBLE || group.Type == logic.THREE) && group.Value < 15 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLE || group.Type == logic.DOUBLE || group.Type == logic.THREE ||
			group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.FOURANDSINGLETWO || group.Type == logic.FOURANDDOUBLETWO {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.BOMB || group.Type == logic.ROCKET {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range priorityGroups {
		if exist, _ := logic.SearchLargerCardType(group.Cards, rb.leftCards, false); !exist {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
			return
		}
	}
	errors.Check(false, errors.ErrorLogic, " can't find abs big cards, maybe error occur !!!")
}

func (rb *robot) doGenCard(min int, max int, isFromBig bool, isForce bool, isUseBomb bool, isUseRocket bool) {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "GenCard is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doGenCard --- ", min, max, isFromBig, isForce, isUseBomb, isUseRocket)
	//先在现有牌组里搜索
	var group *logic.CardGroup
	if isFromBig {
		group = logic.SearchLastLargeGroup(rb.cardGroups, rb.maxOutCards, false)
	} else {
		group = logic.SearchFirstLargeGroup(rb.cardGroups, rb.maxOutCards, false)
	}
	if nil != group {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
		return
	}
	if isForce {
		//在所有手牌中搜索, 除炸弹之外的
		if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
			var out []logic.Card
			if isFromBig {
				out = result[len(result)-1]
			} else {
				out = result[0]
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, out)
			return
		}
	}
	if isUseBomb {
		if exist, result := logic.SearchAllBombs(rb.handCards); exist {
			for _, cards := range result {
				if logic.CompareCards(rb.maxOutCards, cards) {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
					return
				}
			}
		}
	}
	if isUseRocket {
		if exist, result := logic.SearchRocket(rb.handCards); exist {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result)
			return
		}
	}
	//最后没找到，则过牌
	rb.doPassCard()
}

func (rb *robot) doOutSingle(min int, max int, isFromBig bool, isForce bool) {
	errors.Check(nil == rb.maxOutCards, errors.ErrorLogic, "OutSingle is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doOutSingle --- ", min, max, isFromBig, isForce)
	//是否全单张出牌
	if rb.isAllSingleOut() {
		return
	}
	//先在拆分牌型里面找
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLE && group.Value < 15 {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
			return
		}
	}
	_, counts := logic.GetCardCounts(rb.handCards)
	//再找小于J的单张，从最小的找起
	for num, ct := range counts {
		if ct >= 4 {
			continue
		}
		if ct >= 1 && num < 15 {
			var outcards []logic.Card
			for _, card := range rb.handCards {
				if card.Number == num {
					outcards = append(outcards, card)
					break
				}
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, outcards)
			return
		}
	}
	rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, []logic.Card{rb.handCards[0]})
}

func (rb *robot) doOutNotSingle(min int, max int, isFromBig bool, isForce bool) {
	errors.Check(nil == rb.maxOutCards, errors.ErrorLogic, "OutNotSingle is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doOutNotSingle --- ", min, max, isFromBig, isForce)
	//是否全单张出牌
	//if rb.isAllSingleOut() {
	//	return
	//}
	//按价值排序
	rb.cardGroups = logic.SortCardGroupsByValue(rb.cardGroups)
	if isFromBig {
		f := func(s interface{}) {
			n := reflect.ValueOf(s).Len()
			swap := reflect.Swapper(s)
			for i, j := 0, n-1; i < j; i, j = i+1, j-1 {
				swap(i, j)
			}
		}
		f(rb.cardGroups)
	}
	//优先级牌组，排在前面的优先被打出
	var priorityGroups []*logic.CardGroup
	for _, group := range rb.cardGroups {
		if group.Type == logic.AIRPLANEANDSINGLE || group.Type == logic.AIRPLANEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLESTRAIGHT || group.Type == logic.DOUBLESTRAIGHT || group.Type == logic.THREESTRAIGHT {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE) && group.Value < 15 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.DOUBLE || group.Type == logic.THREE) && group.Value < 15 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.DOUBLE || group.Type == logic.THREE ||
			group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.FOURANDSINGLETWO || group.Type == logic.FOURANDDOUBLETWO {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.BOMB || group.Type == logic.ROCKET {
			priorityGroups = append(priorityGroups, group)
		}
	}
	//for _, group := range priorityGroups {
	//	rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
	//	return
	//}
	rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, priorityGroups[0].Cards)
	//rb.doOutCardToStopBanker(priorityGroups)
	//errors.Check(false, errors.ErrorLogic, " why can't find groups cards, maybe error occur !!!")
}

func (rb *robot) doOutDouble(min int, max int, isFromBig bool, isForce bool) {
	errors.Check(nil == rb.maxOutCards, errors.ErrorLogic, "OutDouble is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doOutDouble --- ", min, max, isFromBig, isForce)
	//先在拆分牌型里面找
	for _, group := range rb.cardGroups {
		if group.Type == logic.DOUBLE && group.Value < 15 {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
			return
		}
	}
	//牌个数
	_, counts := logic.GetCardCounts(rb.handCards)
	for num, ct := range counts {
		if ct >= 2 && num < 15 {
			var outcards []logic.Card
			for _, card := range rb.handCards {
				if card.Number == num {
					outcards = append(outcards, card)
					if len(outcards) >= 2 {
						break
					}
				}
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, outcards)
			return
		}
	}
	//没有找到就默认出牌
	rb.doOutCard()
}

func (rb *robot) doOutNotDouble(min int, max int, isFromBig bool, isForce bool) {
	errors.Check(nil == rb.maxOutCards, errors.ErrorLogic, "OutNotDouble is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doOutNotDouble --- ", min, max, isFromBig, isForce)
	// 如果手上全是对子
	if logic.IsGroupsAllDouble(rb.cardGroups) {
		_, counts := logic.GetCardCounts(rb.handCards)
		//再找小于J的单张，从最小的找起
		for num, ct := range counts {
			if ct >= 4 {
				continue
			}
			if ct >= 1 && num < 15 {
				var outcards []logic.Card
				for _, card := range rb.handCards {
					if card.Number == num {
						outcards = append(outcards, card)
						break
					}
				}
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, outcards)
				return
			}
		}
		//打出最小单张
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, []logic.Card{rb.handCards[0]})
		return
	}
	//按价值排序
	rb.cardGroups = logic.SortCardGroupsByValue(rb.cardGroups)
	//优先级牌组，排在前面的优先被打出
	var priorityGroups []*logic.CardGroup
	for _, group := range rb.cardGroups {
		if group.Type == logic.AIRPLANEANDSINGLE || group.Type == logic.AIRPLANEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLESTRAIGHT || group.Type == logic.DOUBLESTRAIGHT || group.Type == logic.THREESTRAIGHT {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE) && group.Value < 15 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if (group.Type == logic.SINGLE || group.Type == logic.THREE) && group.Value < 15 {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.SINGLE || group.Type == logic.THREE ||
			group.Type == logic.THREEANDSINGLE || group.Type == logic.THREEANDDOUBLE {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.FOURANDSINGLETWO || group.Type == logic.FOURANDDOUBLETWO {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for i := len(rb.cardGroups) - 1; i >= 0; i-- {
		if rb.cardGroups[i].Type == logic.DOUBLE {
			priorityGroups = append(priorityGroups, rb.cardGroups[i])
		}
	}
	for _, group := range rb.cardGroups {
		if group.Type == logic.BOMB || group.Type == logic.ROCKET {
			priorityGroups = append(priorityGroups, group)
		}
	}
	for _, group := range priorityGroups {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
		return
	}
	errors.Check(false, errors.ErrorLogic, " why can't find groups cards, maybe error occur !!!")
}

// 被动出牌：出炸弹
func (rb *robot) doOutBomb() {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "OutBomb is illegal !!!")
	if exist, result := logic.SearchAllBombs(rb.handCards); exist {
		for _, cards := range result {
			if logic.CompareCards(rb.maxOutCards, cards) {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
				return
			}
		}
	}
	if exist, result := logic.SearchRocket(rb.handCards); exist {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result)
		return
	}
	//最后没找到，则过牌
	rb.doPassCard()
}
func (rb *robot) doOutBombMax() {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "OutBomb is illegal !!!")
	if exist, result := logic.SearchAllBombs(rb.handCards); exist {
		//for _, cards := range result {
		//	if logic.CompareCards(rb.maxOutCards, cards) {
		//		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
		//		return
		//	}
		//}
		for idx := len(result)-1; idx >= 0; idx-- {
			if logic.CompareCards(rb.maxOutCards, result[idx]) {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[idx])
				return
			}
		}
	}
	if exist, result := logic.SearchRocket(rb.handCards); exist {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result)
		return
	}
	//最后没找到，则过牌
	rb.doPassCard()
}
func (rb *robot) doOut4With2DoubleOr2Single() {
	c := rb.getCardsByGroup(logic.FOURANDDOUBLETWO)
	if len(c) == 0 {
		c = rb.getCardsByGroup(logic.FOURANDSINGLETWO)
	}
	if len(c) > 0 {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, c[0].Cards)
	} else {
		//最后没找到，则过牌
		rb.doPassCard()
	}
}
func (rb *robot) doOutCardToStopBanker(priorityGroups []*logic.CardGroup) {
	var outCards []logic.Card
	if priorityGroups[0].Type != logic.SINGLE {
		outCards = priorityGroups[0].Cards
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, outCards)
		return
	}

	singles := make([]*logic.CardGroup, 0)
	for _, g := range priorityGroups {
		if g.Type == logic.SINGLE {
			singles = append(singles, g)
		}
	}
	for i := len(singles) - 1; i >= 0; i-- {
		g := singles[i]

		if (g.Cards[0].Number == int(logic.C2) || g.Cards[0].Number == int(logic.CBlackJoker) || g.Cards[0].Number == int(logic.CRedJoker)) && i > 0 {
			continue
		}
		if rb.standCard == nil {
			outCards = g.Cards
			break
		} else {
			if g.Value >= rb.standCard.Value() {
				if i > 0 {
					continue
				} else {
					outCards = g.Cards
				}
			} else {
				outCards = g.Cards
				break
			}
		}
	}

	rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, outCards)
}

// 主动出牌：出最小单张
func (rb *robot) doOutMinSingle() {
	errors.Check(nil == rb.maxOutCards, errors.ErrorLogic, "OutMinSingle is illegal !!!")
	_, counts := logic.GetCardCounts(rb.handCards)
	//再找小于J的单张，从最小的找起
	for num, ct := range counts {
		if ct >= 4 {
			continue
		}
		if ct >= 1 && num < 15 {
			var outcards []logic.Card
			for _, card := range rb.handCards {
				if card.Number == num {
					outcards = append(outcards, card)
					break
				}
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, outcards)
			return
		}
	}
	rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, []logic.Card{rb.handCards[0]})
}

// 主动出牌：出最小对子
func (rb *robot) doOutMinDouble() {
	errors.Check(nil == rb.maxOutCards, errors.ErrorLogic, "OutMinDouble is illegal !!!")
	//牌个数
	//先找小于J的对子，从最小的找起
	_, counts := logic.GetCardCounts(rb.handCards)
	for num, ct := range counts {
		if ct >= 4 {
			continue
		}
		if ct >= 2 && num < 11 {
			var outcards []logic.Card
			for _, card := range rb.handCards {
				if card.Number == num {
					outcards = append(outcards, card)
					if len(outcards) >= 2 {
						break
					}
				}
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, outcards)
			return
		}
	}
	//再找小于J的单张，从最小的找起
	for num, ct := range counts {
		if ct >= 4 {
			continue
		}
		if ct >= 1 && num < 11 {
			var outcards []logic.Card
			for _, card := range rb.handCards {
				if card.Number == num {
					outcards = append(outcards, card)
					break
				}
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, outcards)
			return
		}
	}
	//否则按照默认出牌
	rb.doOutCard()
}
func (rb *robot) followCardAction() []logic.Card {
	var res []logic.Card
	if len(rb.maxOutCards) == 1 && rb.maxOutCards[0].Number < int(logic.C2) {
		card2s := rb.getCard(logic.C2)
		if len(card2s) == 3 || len(card2s) == 2 {
			res = card2s[:1]
			return res
		}

		if rb.standCard != nil {
			outCard := [1]*logic.Card{nil}
			for true {
				double := rb.getCardsByGroup(logic.DOUBLE)
				if len(double) > 0 {
					if double[0].Cards[0].Value() >= rb.standCard.Value() {
						outCard[0] = &double[0].Cards[0]
						break
					}
				}
				t3 := rb.getCardsByGroup(logic.THREE)
				if len(t3) > 0 {
					if t3[0].Cards[0].Value() >= rb.standCard.Value() {
						outCard[0] = &t3[0].Cards[0]
						break
					}
				}
				if len(double) > 0 {
					if double[0].Cards[0].Value() == rb.standCard.Value()-1 {
						outCard[0] = &double[0].Cards[0]
						break
					}
				}
				if len(t3) > 0 {
					if t3[0].Cards[0].Value() == rb.standCard.Value()-1 {
						outCard[0] = &t3[0].Cards[0]
						break
					}
				}
				break
			}
			if outCard[0] == nil {
				return nil
			} else {
				res = append(res, *outCard[0])
				return res
			}
		}
	}
	if len(rb.maxOutCards) == 2 && rb.maxOutCards[0].Number < int(logic.C2) {
		card2s := rb.getCard(logic.C2)
		if len(card2s) == 3 {
			res = card2s[:2]
			return res
		}

		if rb.standCard != nil {
			outCard := [2]*logic.Card{nil}
			for true {
				t3 := rb.getCardsByGroup(logic.THREE)
				if len(t3) > 0 {
					if t3[0].Cards[0].Value() >= rb.standCard.Value() {
						outCard[0] = &t3[0].Cards[0]
						outCard[1] = &t3[0].Cards[1]
						break
					}
				}
				break
			}
			if outCard[0] == nil {
				return nil
			} else {
				res = []logic.Card{*outCard[0], *outCard[1]}
			}
		}
	}
	if len(res) == 0 {
		return nil
	}
	return res
}
func (rb *robot) makeSureValueInRange(min int, max int) []*logic.CardGroup {
	c := make([]*logic.CardGroup, len(rb.cardGroups))
	copy(c, rb.cardGroups)
	i := 0
	for _, g := range c {
		if g.Value >= min && g.Value <= max {
			c[i] = g
			i++
		}
	}
	c = c[:i]
	return c
}

// 地主跟上家的出牌
func (rb *robot) doBankerGenPrevOut(min int, max int, isFromBig bool, isForce bool, isUseBomb bool, isUseRocket bool) {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "BankerGenPrevOut is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doBankerGenPrevOut --- ", min, max, isFromBig, isForce, isUseBomb, isUseRocket)
	//是否稳赢
	if ok, cards := logic.GenCardCanAbsWin(rb.cardGroups, rb.handCards, rb.maxOutCards, rb.leftCards, false); ok {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
		return
	}

	cg := rb.makeSureValueInRange(min, max)
	var group *logic.CardGroup

	if isForce {
		//在所有手牌中搜索, 除炸弹之外的
		if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
			var out []logic.Card
			if isFromBig {
				out = result[len(result)-1]
			} else {
				out = result[0]
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, out)
			return
		}
	}

	//先在现有牌组里搜索
	if isFromBig {
		group = logic.SearchLastLargeGroup(cg, rb.maxOutCards, false)
	} else {
		group = logic.SearchFirstLargeGroup(cg, rb.maxOutCards, false)
	}
	if nil != group {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
		return
	}
	c := rb.followCardAction()
	if c != nil {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, c)
		return
	}
	if isUseBomb {
		if exist, result := logic.SearchAllBombs(rb.handCards); exist {
			for _, cards := range result {
				if logic.CompareCards(rb.maxOutCards, cards) {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
					return
				}
			}
		}
	}
	if isUseRocket {
		if exist, result := logic.SearchRocket(rb.handCards); exist {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result)
			return
		}
	}
	//最后没找到，则过牌
	rb.doPassCard()
}

// 地主跟下家的出牌, 由于逆时针出牌顺序，可以判断地主上家是pass
func (rb *robot) doBankerGenNextOut(min int, max int, isFromBig bool, isForce bool, isUseBomb bool, isUseRocket bool) {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "BankerGenNextOut is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doBankerGenNextOut --- ", min, max, isFromBig, isForce, isUseBomb, isUseRocket)
	//是否稳赢
	if ok, cards := logic.GenCardCanAbsWin(rb.cardGroups, rb.handCards, rb.maxOutCards, rb.leftCards, false); ok {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
		return
	}
	//先在现有牌组里搜索
	var group *logic.CardGroup
	cg := rb.makeSureValueInRange(min, max)
	if isForce {
		//在所有手牌中搜索, 除炸弹之外的
		if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
			var out []logic.Card
			if isFromBig {
				out = result[len(result)-1]
			} else {
				out = result[0]
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, out)
			return
		}
	}
	if isFromBig {
		group = logic.SearchLastLargeGroup(cg, rb.maxOutCards, false)
	} else {
		group = logic.SearchFirstLargeGroup(cg, rb.maxOutCards, false)
	}
	if nil != group {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
		return
	}
	c := rb.followCardAction()
	if c != nil {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, c)
		return
	}

	if isUseBomb {
		if exist, result := logic.SearchAllBombs(rb.handCards); exist {
			for _, cards := range result {
				if logic.CompareCards(rb.maxOutCards, cards) {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
					return
				}
			}
		}
	}
	if isUseRocket {
		if exist, result := logic.SearchRocket(rb.handCards); exist {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result)
			return
		}
	}
	//最后没找到，则过牌
	rb.doPassCard()
}

// 地主上家跟地主的出牌, 由于逆时针出牌顺序，可以判断地主下家是pass
func (rb *robot) doPrevGenBankerOut(min int, max int, isFromBig bool, isForce bool, isUseBomb bool, isUseRocket bool) {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "PrevGenBankerOut is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doPrevGenBankerOut --- ", min, max, isFromBig, isForce, isUseBomb, isUseRocket)
	//是否稳赢
	if ok, cards := logic.GenCardCanAbsWin(rb.cardGroups, rb.handCards, rb.maxOutCards, rb.leftCards, false); ok {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
		return
	}
	//出牌为单张，对子时，特殊处理
	cardstype := logic.GetCardsType(rb.maxOutCards)
	if cardstype == logic.SINGLE {
		//在所有手牌中搜索, 除炸弹之外的
		if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
			//地主只剩一张牌
			if rb.handCardsCount[rb.bankerSeat] == 1 {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[len(result)-1])
				return
			}
			//先在现有牌组里搜索
			largeGroups := logic.SearchAllLargeGroups(rb.cardGroups, rb.maxOutCards, false)
			//先找k到2，顺序
			for _, group := range largeGroups {
				if group.Value >= 12 && group.Value <= 15 {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
					return
				}
			}
			//再找2
			for i := 0; i < len(result); i++ {
				if result[i][0].Number == 15 {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[i])
					return
				}
			}
			// //找大小王
			// for _, group := range largeGroups {
			// 	if group.Value > 15 {
			// 		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
			// 		return
			// 	}
			// }
			//找2以下的，逆序
			for i := len(result) - 1; i >= 0; i-- {
				if result[i][0].Number < 15 {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[i])
					return
				}
			}
			//再找大王，小王
			for i := 0; i < len(result); i++ {
				if result[i][0].Number > 15 {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[i])
					return
				}
			}
		}
	} else if cardstype == logic.DOUBLE {
		//在所有手牌中搜索, 除炸弹之外的
		if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
			//地主只剩两张牌
			if rb.handCardsCount[rb.bankerSeat] == 2 {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[len(result)-1])
				return
			}
			//在现有牌组里搜索
			largeGroups := logic.SearchAllLargeGroups(rb.cardGroups, rb.maxOutCards, false)
			if len(largeGroups) > 0 {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, largeGroups[0].Cards)
				return
			}
			//出对子
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[0])
			return
		}
	} else {
		//先在现有牌组里搜索
		var group *logic.CardGroup
		cg := rb.makeSureValueInRange(min, max)
		if isForce {
			//在所有手牌中搜索, 除炸弹之外的
			if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
				var out []logic.Card
				if isFromBig {
					out = result[len(result)-1]
				} else {
					out = result[0]
				}
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, out)
				return
			}
		}
		if isFromBig {
			group = logic.SearchLastLargeGroup(cg, rb.maxOutCards, false)
		} else {
			group = logic.SearchFirstLargeGroup(cg, rb.maxOutCards, false)
		}
		if nil != group {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
			return
		}
		c := rb.followCardAction()
		if c != nil {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, c)
			return
		}

	}
	if isUseBomb {
		if exist, result := logic.SearchAllBombs(rb.handCards); exist {
			for _, cards := range result {
				if logic.CompareCards(rb.maxOutCards, cards) {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
					return
				}
			}
		}
	}
	if isUseRocket {
		if exist, result := logic.SearchRocket(rb.handCards); exist {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result)
			return
		}
	}
	//最后没找到，则过牌
	rb.doPassCard()
}

// 地主上家跟地主下家的出牌
func (rb *robot) doPrevGenNextOut(min int, max int, isFromBig bool, isForce bool, isUseBomb bool, isUseRocket bool) {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "PrevGenNextOut is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doPrevGenNextOut --- ", min, max, isFromBig, isForce, isUseBomb, isUseRocket)
	//判断地主能否打过出牌, 地主打不过则过牌
	if rb.isPlayerNotOut(rb.bankerSeat, false) {
		rb.doPassCard()
		return
	}
	//是否稳赢
	//if ok, cards := logic.GenCardCanAbsWin(rb.cardGroups, rb.handCards, rb.maxOutCards, rb.leftCards, true); ok {
	//	rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
	//	return
	//}
	//判断地主能否打过出牌, 地主打不过则过牌
	//if rb.handCardsCount[(rb.bankerSeat+1)%3] <= 2 {
	//	rb.doPassCard()
	//	return
	//}
	//出牌为单张，对子时，特殊处理
	cardstype := logic.GetCardsType(rb.maxOutCards)
	if cardstype == logic.SINGLE {
		//在所有手牌中搜索, 除炸弹之外的
		if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
			//地主只剩一张牌
			if rb.handCardsCount[rb.bankerSeat] == 1 {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[len(result)-1])
				return
			}
			//先在现有牌组里搜索
			largeGroups := logic.SearchAllLargeGroups(rb.cardGroups, rb.maxOutCards, false)
			//先找k到2，顺序
			for _, group := range largeGroups {
				if group.Value >= min && group.Value <= max {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
					return
				}
			}
			// //再找2
			// for i := 0; i < len(result); i++ {
			// 	if result[i][0].Number == 15 {
			// 		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[i])
			// 		return
			// 	}
			// }
			// //找大小王
			// for _, group := range largeGroups {
			// 	if group.Value > 15 {
			// 		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
			// 		return
			// 	}
			// }
			//找2以下的，逆序
			for i := len(result) - 1; i >= 0; i-- {
				if result[i][0].Number < 15 {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[i])
					return
				}
			}
			// //再找大王，小王
			// for i := 0; i < len(result); i++ {
			// 	if result[i][0].Number > 15 {
			// 		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[i])
			// 		return
			// 	}
			// }
		}
	} else if cardstype == logic.DOUBLE {
		//在所有手牌中搜索, 除炸弹之外的
		if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
			//地主只剩两张牌
			if rb.handCardsCount[rb.bankerSeat] == 2 {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[len(result)-1])
				return
			}
			//在现有牌组里搜索
			largeGroups := logic.SearchAllLargeGroups(rb.cardGroups, rb.maxOutCards, false)
			if len(largeGroups) >= min && largeGroups[0].Value <= max {
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, largeGroups[0].Cards)
				return
			}
			// //出对子
			// rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[0])
			// return
		}
	} else {
		//先在现有牌组里搜索
		var group *logic.CardGroup
		if isForce {
			//在所有手牌中搜索, 除炸弹之外的
			if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
				var out []logic.Card
				if isFromBig {
					out = result[len(result)-1]
				} else {
					out = result[0]
				}
				rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, out)
				return
			}
		}
		if isFromBig {
			group = logic.SearchLastLargeGroup(rb.cardGroups, rb.maxOutCards, false)
		} else {
			group = logic.SearchFirstLargeGroup(rb.cardGroups, rb.maxOutCards, false)
		}
		if nil != group {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
			return
		}
		c := rb.followCardAction()
		if c != nil {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, c)
			return
		}

	}
	if isUseBomb {
		if exist, result := logic.SearchAllBombs(rb.handCards); exist {
			for _, cards := range result {
				if logic.CompareCards(rb.maxOutCards, cards) {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
					return
				}
			}
		}
	}
	if isUseRocket {
		if exist, result := logic.SearchRocket(rb.handCards); exist {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result)
			return
		}
	}
	//最后没找到，则过牌
	rb.doPassCard()
}

// 地主下家跟地主的出牌
func (rb *robot) doNextGenBankerOut(min int, max int, isFromBig bool, isForce bool, isUseBomb bool, isUseRocket bool) {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "NextGenBankerOut is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doNextGenBankerOut --- ", min, max, isFromBig, isForce, isUseBomb, isUseRocket)
	//是否稳赢
	if ok, cards := logic.GenCardCanAbsWin(rb.cardGroups, rb.handCards, rb.maxOutCards, rb.leftCards, false); ok {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
		return
	}
	//isPrevNotOut := rb.isPlayerNotOut((rb.bankerSeat+2)%3, false)
	//if isPrevNotOut {
	//	isForce = true
	//	//队友是否只剩2张以下
	//	if rb.exportData.BankerPrevCardsCount <= 2 {
	//		group := logic.SearchLastLargeGroup(rb.cardGroups, rb.maxOutCards, true)
	//		if nil != group {
	//			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
	//			return
	//		}
	//		if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, true); exist {
	//			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result[len(result)-1])
	//			return
	//		}
	//	}
	//}
	//先在现有牌组里搜索
	var group *logic.CardGroup
	cg := rb.makeSureValueInRange(min, max)
	if isForce {
		//在所有手牌中搜索, 除炸弹之外的
		if exist, result := logic.SearchLargerCardType(rb.maxOutCards, rb.handCards, false); exist {
			var out []logic.Card
			if isFromBig {
				out = result[len(result)-1]
			} else {
				out = result[0]
			}
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, out)
			return
		}
	}
	if isFromBig {
		group = logic.SearchLastLargeGroup(cg, rb.maxOutCards, false)
	} else {
		group = logic.SearchFirstLargeGroup(cg, rb.maxOutCards, false)
	}
	if nil != group {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, group.Cards)
		return
	}
	c := rb.followCardAction()
	if c != nil {
		rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, c)
		return
	}

	if isUseBomb {
		if exist, result := logic.SearchAllBombs(rb.handCards); exist {
			for _, cards := range result {
				if logic.CompareCards(rb.maxOutCards, cards) {
					rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
					return
				}
			}
		}
	}
	if isUseRocket {
		if exist, result := logic.SearchRocket(rb.handCards); exist {
			rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, result)
			return
		}
	}
	//最后没找到，则过牌
	rb.doPassCard()
}

// 地主下家跟地主上家的出牌, 由于逆时针出牌顺序，可以判断地主是pass
func (rb *robot) doNextGenPrevOut(min int, max int, isFromBig bool, isForce bool, isUseBomb bool, isUseRocket bool) {
	errors.Check(nil != rb.maxOutCards, errors.ErrorLogic, "NextGenPrevOut is illegal !!!")
	wplog.Info(rb.robotPlayer.GetDLogPrefix()+" doNextGenPrevOut --- ", min, max, isFromBig, isForce, isUseBomb, isUseRocket)
	//是否稳赢
	//if ok, cards := logic.GenCardCanAbsWin(rb.cardGroups, rb.handCards, rb.maxOutCards, rb.leftCards, true); ok {
	//	rb.sendOutCardmsg(gameddz.OptionType_OP_OUT_CARD, cards)
	//	return
	//}
	//最后没找到，则过牌
	rb.doPassCard()
}
